1 package org.smartcomps.twister.util;
2
3 import org.smartcomps.twister.engine.priv.core.definition.impl.PropertyImpl;
4
5 import org.apache.commons.logging.Log;
6 import org.apache.commons.logging.LogFactory;
7
8 import java.util.HashMap;
9 import java.util.Date;
10 import java.util.Collection;
11 import java.util.ArrayList;
12 import java.lang.reflect.Method;
13 import java.lang.reflect.InvocationTargetException;
14
15 /***
16 * This class simply gives a random value to all properties of a JavaBean and
17 * memorize it so that it can test, later on (after it has been persisted
18 * and reloaded for exemple), that original values are still same.
19 */
20 public class BeanTester {
21
22 private static Log log = LogFactory.getLog(BeanTester.class);
23
24 public static final int STRING_LENGTH = 10;
25
26 private static final long FIFTY_YEARS_MS = 50*360*24*60*60*1000L;
27 private static final String SET_PREFIX = "set";
28 private static final String GET_PREFIX = "get";
29 private static final String IS_PREFIX = "is";
30
31 private HashMap beansValues = new HashMap();
32 private Collection ignoreList = null;
33
34 /***
35 * Default constructor.
36 */
37 public BeanTester() {
38 ignoreList = new ArrayList();
39 }
40
41 /***
42 * Creates a BeanTester with a list of properties that will be ignored. The
43 * BeanTester won't therefore try to assign those properties a value to test
44 * it later on. The first letter of each property must be in high case.
45 * @param ignoreList
46 */
47 public BeanTester(String[] ignoreList) {
48 this.ignoreList = new ArrayList(ignoreList.length);
49 for (int m = 0; m < ignoreList.length; m++) {
50 String ignoreArg = ignoreList[m];
51 this.ignoreList.add(ignoreArg);
52 }
53 }
54
55 /***
56 * Lets the BeanTester initialize all properties of a bean. It isolates all
57 * properties of an object (basically from get and set methods following the
58 * JavaBean specs and accepting simple types (String, Integer, Date, Long,
59 * Boolean)) that aren't in the ignore list and sets them with a random value.
60 * @param name all objects tested by the BeanTester must be named
61 * @param bean object to test
62 */
63 public void initializeProperties(String name, Object bean) {
64 Method[] beanMethods = bean.getClass().getMethods();
65 for (int m = 0; m < beanMethods.length; m++) {
66 Method beanMethod = beanMethods[m];
67 String propName = isProperty(beanMethod);
68 if (propName != null && !ignoreList.contains(propName)) {
69 Object rndValue = generateRandomValue(beanMethod.getParameterTypes()[0]);
70 if (rndValue != null) {
71 boolean setted = false;
72 try {
73 beanMethod.invoke(bean, new Object[]{rndValue});
74 setted = true;
75 } catch (IllegalAccessException e) {
76 throw new RuntimeException("Could not invoke set" + propName + " with value " +
77 rndValue + " on object named " + name, e);
78 } catch (IllegalArgumentException e) {
79 throw new RuntimeException("Could not invoke set" + propName + " with value " +
80 rndValue + " on object named " + name, e);
81 } catch (InvocationTargetException e) {
82 log.warn("Could not invoke set" + propName + " with value " +
83 rndValue + " on object named " + name);
84 }
85 if (setted) {
86 log.info("Testing bean property " + propName + " for " + name);
87 beansValues.put(bean.getClass() + "(" + name + ")." + propName, rndValue);
88 }
89 }
90 }
91 }
92 }
93
94 /***
95 * Tests the values of the properties that have been initialized
96 * @param name must have the same value as for initialization
97 * @param bean to test values
98 * @return true if all properties have the same values in the provided bean
99 */
100 public boolean testValues(String name, Object bean) {
101 boolean result = true;
102
103 Method[] beanMethods = bean.getClass().getMethods();
104 for (int m = 0; m < beanMethods.length; m++) {
105 Method beanMethod = beanMethods[m];
106 String propName = isProperty(beanMethod);
107 if (propName != null && !ignoreList.contains(propName)) {
108 Object originalValue = beansValues.get(bean.getClass() + "(" + name + ")." + propName);
109 if (originalValue != null) {
110 Object currValue = null;
111 try {
112 Method getter = null;
113 try {
114 getter = bean.getClass().getMethod(GET_PREFIX + propName, new Class[]{});
115 } catch (NoSuchMethodException e) {
116 getter = bean.getClass().getMethod(IS_PREFIX + propName, new Class[]{});
117 }
118 currValue = getter.invoke(bean, new Object[]{});
119 } catch (NoSuchMethodException e) {
120 throw new RuntimeException("Could not find get" + propName + " on object named " + name, e);
121 } catch (SecurityException e) {
122 throw new RuntimeException("Could not find get" + propName + " on object named " + name, e);
123 } catch (IllegalAccessException e) {
124 throw new RuntimeException("Could not invoke get" + propName + " on object named " + name, e);
125 } catch (InvocationTargetException e) {
126 throw new RuntimeException("Could not invoke get" + propName + " on object named " + name, e);
127 }
128
129 if (originalValue == null) {
130 if (currValue != null) {
131 result = false;
132 log.warn("Property " + propName + " changed, before " + originalValue +", now " + currValue);
133 }
134 } else if (!originalValue.equals(currValue)) {
135 result = false;
136 log.warn("Property " + propName + " changed, before " + originalValue +", now " + currValue);
137 }
138 }
139 }
140 }
141
142 return result;
143 }
144
145 public static Object generateRandomValue(Class aClass) {
146 Object result = null;
147
148 double rand = Math.random();
149 if (aClass.equals(String.class)) {
150 result = "" + Math.round(rand * Math.pow(10, STRING_LENGTH));
151 } else if (aClass.equals(Integer.TYPE)) {
152 result = new Integer(new Long(Math.round(rand * Integer.MAX_VALUE)).intValue());
153 } else if (aClass.equals(Long.TYPE)) {
154 result = new Long(Math.round(rand * Integer.MAX_VALUE));
155 } else if (aClass.equals(Boolean.TYPE)) {
156 result = new Boolean(rand < 0.5);
157 } else if (aClass.equals(Date.class)) {
158 result = new Date(Math.round(rand * FIFTY_YEARS_MS));
159 }
160
161 return result;
162 }
163
164 private String isProperty(Method method) {
165
166 // Isolate a property from its set method
167 if (!method.getName().startsWith(SET_PREFIX)) {
168 return null;
169 }
170
171 // If setter has not exactly one parameter, it's not a right setter
172 if (method.getParameterTypes().length == 0 || method.getParameterTypes().length > 1) {
173 return null;
174 }
175
176 if (Collection.class.isAssignableFrom(method.getParameterTypes()[0])) {
177 return null;
178 }
179
180 // Must have a getter with same name
181 String propertyName = method.getName().substring(3);
182 Method correspondingGet = null;
183 Method[] methods = method.getDeclaringClass().getMethods();
184 for (int m = 0; m < methods.length; m++) {
185 Method anotherMethod = methods[m];
186 String anMethName = anotherMethod.getName();
187 if (anMethName.equals(GET_PREFIX + propertyName) || anMethName.equals(IS_PREFIX + propertyName)) {
188 if (anotherMethod.getParameterTypes().length == 0) {
189 correspondingGet = anotherMethod;
190 }
191 }
192 }
193 if (correspondingGet == null) return null;
194
195 // Getter must return something
196 if (correspondingGet.getReturnType() == null) return null;
197
198 // Getter must return same type has setter accepts
199 if (!correspondingGet.getReturnType().equals(method.getParameterTypes()[0])) {
200 return null;
201 }
202
203 return propertyName;
204 }
205
206 // public static void main(String[] args) {
207 // BeanTester tester = new BeanTester(new String[] {"Id"});
208 // PropertyImpl testBean = new PropertyImpl();
209 // testBean.setName("aName");
210 // testBean.setType("aType");
211 //
212 // tester.initializeProperties("testBean", testBean);
213 // testBean.setId(new Long(12));
214 // testBean.setName("anotherName");
215 // System.out.println("Result : " + tester.testValues("testBean", testBean));
216 // }
217 }
This page was automatically generated by Maven